﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using ImageProvider;

namespace ImageLib
{
    public class ImageUser
    {
        private readonly ImageProviderBase provider;
        private readonly ImageCatalogue root;
        private readonly ImageSecurity security;

        public ImageUser(string name, ImageProviderBase provider)
        {
            this.Name = name;
            this.provider = provider;
            this.security = new ImageSecurity();
            this.root = this.AddCatalogue(name);
        }

        public string Name { get; private set; }

        public ImageCatalogue Root
        {
            get { return this.root; }
        }

        public string RootPath
        {
            get { return "*"; }
        }

        public ImageCatalogue AddCatalogue(string name, ImageCatalogue parent = null)
        {
            parent = parent ?? this.Root;
            var path = parent != null ? parent.Path : this.RootPath;
            var catalogue = default(ImageCatalogue);
            var isAllowed = this.security.IsAllowed(path, "create_folder", this.Name);
            if (isAllowed)
            {
                catalogue = this.provider.AddCatalogue(name, parent);
                Console.WriteLine("{0, 5}: Catalogue '{1}' added in catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , path == this.RootPath ? "root" : path);
            }
            else
            {
                Console.WriteLine("{0, 5}: Access denied. Catalogue '{1}' cannot be added in catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , string.IsNullOrEmpty(path) ? "root" : path);
            }

            return catalogue;
        }

        public Image DownloadImage(string name, ImageCatalogue catalogue = null)
        {
            catalogue = catalogue ?? this.Root;
            var image = this.provider.RetrieveImage(name, catalogue);
            var path = Path.Combine(catalogue.Name, name);
            var isAllowed = this.security.IsAllowed(path, "download", this.Name);
            if (isAllowed)
            {
                Console.WriteLine("{0, 5}: Image '{1}' retrieved from catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , string.IsNullOrEmpty(path) ? "root" : catalogue.Name);
            }
            else
            {
                Console.WriteLine("{0, 5}: Access denied. Image '{1}' cannot be retrieved from catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , string.IsNullOrEmpty(path) ? "root" : catalogue.Name);
            }

            return image;
        }

        public IEnumerable<ImageCatalogue> GetCatalogues(ImageCatalogue parent = null)
        {
            parent = parent ?? this.Root;
            var path = parent.Path;
            var isAllowed = this.security.IsAllowed(path, "list_folders", this.Name);
            if (isAllowed)
            {
                var catalogues = this.provider.RetrieveCatalogues(parent);
                Console.WriteLine("{0, 5}: Catalogues in catalogue '{1}' retrieved"
                    , this.Name.ToUpper()
                    , string.IsNullOrEmpty(path) ? "root" : path);
                return catalogues;
            }

            Console.WriteLine("{0, 5}: Access denied. Catalogues in catalogue '{1}' cannot be retrieved"
                , this.Name.ToUpper()
                , string.IsNullOrEmpty(path) ? "root" : path);
            return null;
        }

        public void UploadImage(string name, Image image, ImageCatalogue catalogue = null)
        {
            catalogue = catalogue ?? this.Root;
            var path = Path.Combine(catalogue.Name, name);
            var isAllowed = this.security.IsAllowed(path, "upload", this.Name);
            if (isAllowed)
            {
                image.Tag = name;
                this.provider.SaveImage(name, image, catalogue);
                Console.WriteLine("{0, 5}: Image '{1}' saved in catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , string.IsNullOrEmpty(path) ? "root" : catalogue.Name);
            }
            else
            {
                Console.WriteLine("{0, 5}: Access denied. Image '{1}' cannot be saved in catalogue '{2}'"
                    , this.Name.ToUpper()
                    , name
                    , string.IsNullOrEmpty(path) ? "root" : catalogue.Name);
            }
        }
    }
}